﻿// License: The MIT License (MIT) Copyright (c) 2011..2012 Barend Gehrels

// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using WPF.JoshSmith.ServiceProviders.UI;

namespace GrooveSharp
{
    public partial class CurrentPlayList : UserControl, IPlayer
    {

        #region EVENT REGISTRATION
        public static readonly RoutedEvent PlayOtherTrackEvent =
                  EventManager.RegisterRoutedEvent("PlayOtherTrack", RoutingStrategy.Bubble,
                    typeof(RoutedEventHandler), typeof(MainPlayer));
        public static readonly RoutedEvent OnTrackOrderChangedEvent =
                  EventManager.RegisterRoutedEvent("OnTrackOrderChanged", RoutingStrategy.Bubble,
                    typeof(RoutedEventHandler), typeof(MainPlayer));

        public event RoutedEventHandler PlayOtherTrack
        {
            add { AddHandler(PlayOtherTrackEvent, value); }
            remove { RemoveHandler(PlayOtherTrackEvent, value); }
        }
        public event RoutedEventHandler OnTrackOrderChanged
        {
            add { AddHandler(OnTrackOrderChangedEvent, value); }
            remove { RemoveHandler(OnTrackOrderChangedEvent, value); }
        }

        public event RoutedEventHandler RatingChanged
        {
            add { AddHandler(Rating.RatingChangedEvent, value); }
            remove { RemoveHandler(Rating.RatingChangedEvent, value); }
        }

        #endregion

        ListViewDragDropManager<TrackInfo> dragMgr;

        private int m_selectedId = 0;
        private TrackRating m_lastChangedRating = new TrackRating();

        public int SelectedId
        {
            get
            {
                return m_selectedId;
            }
        }

        public TrackRating LastChangedRating
        {
            get
            {
                return m_lastChangedRating;
            }
        }

        public CurrentPlayList()
        {
            InitializeComponent();

            listViewCurrentPlayList.ItemsSource = TrackInfoCollection.Collection();
            this.dragMgr = new ListViewDragDropManager<TrackInfo>(this.listViewCurrentPlayList);
            //this.dragMgr.ProcessDrop += dragMgr_ProcessDrop;
            this.listViewCurrentPlayList.Drop += OnListViewDrop;
        }

        public void Play(TrackInfo info)
        {
            foreach (TrackInfo li in TrackInfoCollection.Collection())
            {
                li.Playing = li.Id == info.Id;
            }
            m_selectedId = info.Id;
        }

        public void Stop()
        {
            foreach (TrackInfo li in TrackInfoCollection.Collection())
            {
                li.Playing = false;
            }
            m_selectedId = 0;
        }


        private void RadioButton_Click(object sender, RoutedEventArgs e)
        {
            if (sender is RadioButton)
            {
                RadioButton radio = sender as RadioButton;
                int id = 0;
                if (radio.IsChecked.Value && Int32.TryParse(radio.Tag.ToString(), out id))
                {
                    m_selectedId = id;
                    RaiseEvent(new RoutedEventArgs(PlayOtherTrackEvent));
                }
            }
        }

        // Performs custom drop logic for the top ListView.
        void dragMgr_ProcessDrop(object sender, ProcessDropEventArgs<TrackInfo> e)
        {
            int high = Math.Max(e.OldIndex, e.NewIndex);
            int low = Math.Min(e.OldIndex, e.NewIndex);

            if (low >= 0 && high >= 0 
                && low < e.ItemsSource.Count && high < e.ItemsSource.Count
                // null values will cause an error when calling Move.
                // It looks like a bug in ObservableCollection to me (Josh Smith)
                && e.ItemsSource[low] != null && e.ItemsSource[high] != null)
            {
                e.ItemsSource.Move(low, high);
                e.ItemsSource.Move(high - 1, low);
            }

            // Set this to 'Move' so that the OnListViewDrop knows to 
            // remove the item from the other ListView.
            e.Effects = DragDropEffects.Move;

            // Raise event that list order has been changed (or so)
        }

        void OnListViewDrop(object sender, DragEventArgs e)
        {
            if (e.Effects == DragDropEffects.None)
                return;

            RaiseEvent(new RoutedEventArgs(OnTrackOrderChangedEvent));

            TrackInfo info = e.Data.GetData(typeof(TrackInfo)) as TrackInfo;
            App.Log.DebugFormat("Dropped track with ID {0}", info.Id);
        }

        private void Rating_RatingChanged(object sender, RoutedEventArgs e)
        {
            if (sender is Rating)
            {
                Rating rating = sender as Rating;
                m_lastChangedRating.TrackId = 0;
                m_lastChangedRating.Value = -1;
                int id = 0;
                if (Int32.TryParse(rating.Tag.ToString(), out id))
                {
                    m_lastChangedRating.TrackId = id;
                    m_lastChangedRating.Value = rating.RatingValue;
                }
            }
        }

        private void DockPanel_MouseRightButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {

        }

        private void listViewCurrentPlayList_MouseRightButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (e.Source is ListView)
            {
                Object item = (e.Source as ListView).SelectedItem;
                if (item != null && item is TrackInfo)
                {
                    TrackInfo tinfo = item as TrackInfo;

                    //if (tag != null && tag.FileOrFolderName != null)
                    //{
                    //    item.IsSelected = true;
                    //    info.Select(tag.Id, tag.FileOrFolderName);
                    //    
                    //}
                    popupInfo.Select(tinfo.Id, null);
                    popLink.IsOpen = true;
                }
            }
        }

        private void popLink_Closed(object sender, EventArgs e)
        {
            popupInfo.Select(0, "");
        }

        private void removeButton_Click(object sender, RoutedEventArgs e)
        {
            // Two-stage deletion (because cannot enumerate through collection being updated)
            var list = new List<TrackInfo>();
            foreach (var item in listViewCurrentPlayList.SelectedItems)
            {
                if (item is TrackInfo && ! (item as TrackInfo).Playing)
                {
                    list.Add(item as TrackInfo);
                }
            }

            foreach (var item in list)
            {
                TrackInfoCollection.Collection().Remove(item);
            }
        }


    }
}
